package weibo_interface;

import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;

import user_interface.User;

import myutil.GetTable;
import jasona.Services;
import jasona.Services.WeibomMeta;

public class Weibo {
	public static boolean send(Services.WeibomMeta swb) {
		if (User.checkUsername(swb.getUsername()))
			return false;

		 swb.generateWid();
		GetTable gt = new GetTable("weibos");
		GetTable gt2 = new GetTable("userweibo");
		//GetTable gt3 = new GetTable("currentweibo");
		GetTable gt4 = new GetTable("userinfo");
		Put put = new Put(Bytes.toBytes(swb.getWid()));
		byte[] family = Bytes.toBytes("metainfo");
		put.add(family, Bytes.toBytes("username"),
				Bytes.toBytes(swb.getUsername()));
		put.add(family, Bytes.toBytes("content"),
				Bytes.toBytes(swb.getContent()));
		put.add(family, Bytes.toBytes("image_url"), swb.getImg());
		put.add(family, Bytes.toBytes("time"), Bytes.toBytes(swb.getTime()));
		put.add(family, Bytes.toBytes("resend_number"),
				Bytes.toBytes(swb.getResents()));
		put.add(family, Bytes.toBytes("comment_number"),
				Bytes.toBytes(swb.getComments()));

		Put put2 = new Put(
				Bytes.toBytes(swb.getUsername() + "$" + swb.getWid()));
		put2.add(Bytes.toBytes("empty"), Bytes.toBytes("dc"), Bytes.toBytes(""));

		Put put3 = new Put(Bytes.toBytes(swb.getUsername()));
		put3.add(family, Bytes.toBytes("wid"), Bytes.toBytes(swb.getWid()));

		Put put4 =  new Put(Bytes.toBytes(swb.getUsername()));
		put4.add(family, Bytes.toBytes("currentweibo"), Bytes.toBytes(swb.getContent()));
		try {
			gt.ht.put(put);
			gt2.ht.put(put2);
			gt4.ht.put(put4);
			// gt3.ht.put(put3); // no need now
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} finally {
			gt.CloseTable();
			gt2.CloseTable();
			//gt3.CloseTable();
			gt4.CloseTable();
		}
	}

	public static ArrayList<Services.WeibomMeta> getWeibos(String username) {
		if (User.checkUsername(username))
			return null;
		GetTable gt = new GetTable("userweibo");
		HTable ht = gt.ht;
		GetTable gt2 = new GetTable("weibos");
		HTable ht2 = gt2.ht;
		ArrayList<Services.WeibomMeta> userweibos = new ArrayList<Services.WeibomMeta>();

		// //////////////////////////////////////////////////////////////////////////////////////////////////
		Scan sc = new Scan();
		sc.setStartRow(Bytes.toBytes(username + "#"));
		sc.setStopRow(Bytes.toBytes(username + "~"));
		// ArrayList<byte[]> users = new ArrayList<byte[]>();
		ResultScanner result;
		ArrayList<Get> weibogets = new ArrayList<Get>();
		try {
			result = ht.getScanner(sc);
			for (Result r : result) {
				byte[] user = Bytes.toBytes(Bytes.toString(r.getRow()).replace(
						username + "$", ""));
				// System.out.println(Bytes.toString(user));
				weibogets.add(new Get(user));
			}
			Result[] rs = ht2.get(weibogets);
			byte[] family = Bytes.toBytes("metainfo");
			for (Result r : rs) {
				if (r.isEmpty())
					continue;
				Services.WeibomMeta swbtemp = new Services.WeibomMeta();
				swbtemp.setWid(Bytes.toString(r.getRow()));
				swbtemp.setUsername(Bytes.toString(r.getValue(family,
						Bytes.toBytes("username"))));
				swbtemp.setContent(Bytes.toString(r.getValue(family,
						Bytes.toBytes("content"))));
				swbtemp.setTime(Bytes.toString(r.getValue(family,
						Bytes.toBytes("time"))));
				swbtemp.setResents(Bytes.toInt(r.getValue(family,
						Bytes.toBytes("resend_number"))));
				swbtemp.setComments(Bytes.toInt(r.getValue(family,
						Bytes.toBytes("comment_number"))));
				swbtemp.setImg((r.getValue(family, Bytes.toBytes("image_url"))));

				if (swbtemp != null)
					userweibos.add(swbtemp);
			}
			return userweibos;

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			gt.CloseTable();
			gt2.CloseTable();
		}
	}

	public static boolean comment(Services.CommentMeta scm) {
		if (User.checkUsername(scm.getUsername()))
			return false;

		scm.generateCid();
		GetTable gt = new GetTable("comment");
		GetTable gt2 = new GetTable("weibocomment");
		GetTable gt3 = new GetTable("weibos");
		Put put = new Put(Bytes.toBytes(scm.getCid()));
		byte[] family = Bytes.toBytes("metainfo");
		/*
		 * public String cid=""; public String wid=""; public String
		 * username="";//(who give comment) public String content=""; public
		 * String time="";
		 */
		put.add(family, Bytes.toBytes("wid"), Bytes.toBytes(scm.getWid()));
		put.add(family, Bytes.toBytes("content"),
				Bytes.toBytes(scm.getContent()));
		put.add(family, Bytes.toBytes("time"), Bytes.toBytes(scm.getTime()));
		put.add(family, Bytes.toBytes("username"),
				Bytes.toBytes(scm.getUsername()));

		Put put2 = new Put(Bytes.toBytes(scm.getWid() + "$" + scm.getCid()));
		put2.add(Bytes.toBytes("empty"), Bytes.toBytes("dc"), Bytes.toBytes(""));

		Put put3 = new Put(Bytes.toBytes(scm.getWid()));
		put3.add(family, Bytes.toBytes("comment_number"),
				Bytes.toBytes(scm.getComment_number() + 1));

		try {
			gt.ht.put(put);
			gt2.ht.put(put2);
			gt3.ht.put(put3);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} finally {
			gt.CloseTable();
			gt2.CloseTable();
			gt3.CloseTable();
		}
	}
	
	public static ArrayList<Services.CommentMeta> getCommnet(String wid) {
		GetTable gt = new GetTable("weibocomment");
		HTable ht = gt.ht;
		GetTable gt2 = new GetTable("comment");
		HTable ht2 = gt2.ht;
		GetTable gt3 = new GetTable("weibos");
		Get g = new Get(Bytes.toBytes(wid));
		ArrayList<Services.CommentMeta> weibocomments = new ArrayList<Services.CommentMeta>();

		// //////////////////////////////////////////////////////////////////////////////////////////////////
		Scan sc = new Scan();
		sc.setStartRow(Bytes.toBytes(wid + "#"));
		sc.setStopRow(Bytes.toBytes(wid + "~"));

		ResultScanner result;
		ArrayList<Get> weibogets = new ArrayList<Get>();
		try {
			int common_comment_number = Bytes
					.toInt(gt3.ht.get(g).getValue(Bytes.toBytes("metainfo"),
							Bytes.toBytes("comment_number")));

			result = ht.getScanner(sc);
			for (Result r : result) {
				byte[] comment = Bytes.toBytes(Bytes.toString(r.getRow())
						.replace(wid + "$", ""));
				// System.out.println(Bytes.toString(user));
				weibogets.add(new Get(comment));
			}
			Result[] rs = ht2.get(weibogets);
			byte[] family = Bytes.toBytes("metainfo");

			for (Result r : rs) {
				if (r.isEmpty())
					continue;
				Services.CommentMeta scm = new Services.CommentMeta();
				scm.setCid(Bytes.toString(r.getRow()));
				scm.setUsername(Bytes.toString(r.getValue(family,
						Bytes.toBytes("username"))));
				scm.setContent(Bytes.toString(r.getValue(family,
						Bytes.toBytes("content"))));
				scm.setTime(Bytes.toString(r.getValue(family,
						Bytes.toBytes("time"))));
				scm.setWid(Bytes.toString(r.getValue(family,
						Bytes.toBytes("wid"))));
				scm.setComment_number(common_comment_number);
				if (scm != null)
					weibocomments.add(scm);
			}
			Collections.sort(weibocomments, new Comparator<Services.CommentMeta>() {
				@Override
				public int compare(Services.CommentMeta arg0,
						Services.CommentMeta arg1) {
					// TODO Auto-generated method stub
					return arg0.getTime().compareTo(arg1.getTime());
				}
			});
			return weibocomments;

		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			gt.CloseTable();
			gt2.CloseTable();
			gt3.CloseTable();
		}
	}

	public static boolean resendupdate(String wid,int current_resend_number)
	{
		GetTable gt = new GetTable("weibos");
		Put put = new Put(Bytes.toBytes(wid)).add(Bytes.toBytes("metainfo"), Bytes.toBytes("resend_number"), Bytes.toBytes(current_resend_number+1));
		try {
			gt.ht.put(put);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();return false;
		}
		finally
		{
			gt.CloseTable();
		}
	}
	
	public static boolean deleteWeibo(String wid) {
		GetTable gt = new GetTable("weibos");
		HTable ht = gt.ht;
		byte[] rowid = Bytes.toBytes(wid);
		Delete dl = new Delete(rowid);
		try {
			ht.delete(dl);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} finally {
			gt.CloseTable();
		}
	}

	public static boolean deleteComment(Services.CommentMeta scm) {
		GetTable gt = new GetTable("comment");
		GetTable gt2 = new GetTable("weibos");
		byte[] rowid = Bytes.toBytes(scm.getCid());
		Delete dl = new Delete(rowid);
		Put put2 = new Put(Bytes.toBytes(scm.getWid()));
		put2.add(Bytes.toBytes("metainfo"), Bytes.toBytes("comment_number"),
				Bytes.toBytes(scm.getComment_number() - 1));
		try {
			gt.ht.delete(dl);
			gt2.ht.put(put2);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} finally {
			gt.CloseTable();
			gt2.CloseTable();
		}

	}

	public static ArrayList<Services.WeibomMeta> getBlockCur(
			String[] usernamelist) {
		ArrayList<Services.WeibomMeta> curblock = new ArrayList<Services.WeibomMeta>();
		ArrayList<Future<Services.WeibomMeta>> midrs = new ArrayList<Future<Services.WeibomMeta>>();

		ExecutorService exec = Executors.newCachedThreadPool();
		Weibo wb = new Weibo();
		for (String username : usernamelist) {
			try {
				midrs.add(exec.submit(wb.new GetSingleWeibo(username)));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		for (Future<WeibomMeta> f : midrs) {
			try {
				if (f.get() != null)
					curblock.add((WeibomMeta) f.get());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				
			}
			finally
			{
				exec.shutdown();
			}
		}
		return curblock;
	}

	public class GetSingleWeibo implements Callable<Services.WeibomMeta> {
		public String username = "";

		public GetSingleWeibo(String username) {
			this.username = username;
		}

		@Override
		public WeibomMeta call() throws Exception {
			// TODO Auto-generated method stub
			ArrayList<WeibomMeta> rs = Weibo.getWeibos(this.getUsername());
			System.out.println("Doing " + this.getUsername());
			if (rs == null)
				return null;
			if (rs.size() == 0)
				return null;
			else {
				// sort
				Collections.sort(rs, new Comparator<Services.WeibomMeta>() {
					@Override
					public int compare(Services.WeibomMeta arg0,
							Services.WeibomMeta arg1) {
						// TODO Auto-generated method stub
						return arg0.getTime().compareTo(arg1.getTime());
					}
				});
				return rs.get(rs.size() - 1);
			}
		}

		public String getUsername() {
			return username;
		}

		public void setUsername(String username) {
			this.username = username;
		}
	}

	public static ArrayList<Services.WeibomMeta> getAllWeibos(String[] usernamelist)
	{
		ArrayList<Services.WeibomMeta> allblock = new ArrayList<Services.WeibomMeta>();
		ArrayList<Future<ArrayList<Services.WeibomMeta>>> midrs = new ArrayList<Future<ArrayList<Services.WeibomMeta>>>();

		ExecutorService exec = Executors.newCachedThreadPool();
		Weibo wb = new Weibo();
		for (String username : usernamelist) {
			try {
				midrs.add(exec.submit(wb.new GetMultiWeibo(username)));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		for (Future<ArrayList<WeibomMeta>> f : midrs) {
			try {
				if (f.get() != null)
					allblock.addAll((ArrayList<WeibomMeta>) f.get());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();			
			}
			finally
			{
				exec.shutdown();
			}
		}
		
		Collections.sort(allblock, new Comparator<Services.WeibomMeta>() {
			@Override
			public int compare(Services.WeibomMeta arg0,
					Services.WeibomMeta arg1) {
				// TODO Auto-generated method stub
				return -arg0.getTime().compareTo(arg1.getTime());
			}
		});
		
		return allblock;
	}
	
	public class GetMultiWeibo implements Callable<ArrayList<Services.WeibomMeta>> {
		public String username = "";

		public GetMultiWeibo(String username) {
			this.username = username;
		}

		@Override
		public ArrayList<WeibomMeta> call() throws Exception {
			// TODO Auto-generated method stub
			ArrayList<WeibomMeta> rs = Weibo.getWeibos(this.getUsername());
			System.out.println("Doing " + this.getUsername());
			if (rs == null)
				return null;
			if (rs.size() == 0)
				return null;
			else {
				// no sort
				return rs;
			}
		}

		public String getUsername() {
			return username;
		}

		public void setUsername(String username) {
			this.username = username;
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		DateFormat df = DateFormat.getDateTimeInstance();
		System.out.print(df.format(new Date()));
		
		Services.WeibomMeta swb = new Services.WeibomMeta();
		swb.setUsername("liutaojason3");
		swb.setContent("kake first weibo 3");
		swb.setImg(null);
		swb.setResents(0);
		swb.setComments(0);
		swb.setTime(df.format(new Date()));
		swb.generateWid();
		//System.out.print(Weibo.send(swb));
		// Weibo.deleteWeibo("-862695284");
		// System.out.println(Weibo.getWeibos("liutaojason").size());
		//for (Services.WeibomMeta swb_it : Weibo.getWeibos("liutaojason")) {
			//System.out.println(swb_it);
			//System.out.println(Weibo.deleteWeibo(swb_it.getWid()));
		//}

		String[] userlist = new String[3];
		userlist[0]=("liutaojason");
		userlist[1]=("liutaojason2");
		userlist[2]=("liutaojason3");
		//for (Services.WeibomMeta s : Weibo.getAllWeibos(userlist)) {
		//	System.out.println(s);
		//}

		Services.CommentMeta scm = new Services.CommentMeta();
		//scm.setUsername("liutaojason2");
		//scm.setContent("comments3");
		//scm.setTime(df.format(new Date()));
		//scm.setWid("740687823");
		scm.setCid("-971966992");
		scm.setWid("-820172731");
		scm.setComment_number(3);// fake set the wid.comment_number
		// scm.generateCid();
		// scm.setCid("-1702595769");
		// Weibo.comment(scm);
		System.out.println(Weibo.deleteComment(scm));
		 for (Services.CommentMeta scm_it : Weibo.getCommnet("-820172731")) {
		 System.out.println(scm_it);
		 }
	}
}
